#region License

// This file is part of Grawlix.
// 
// Grawlix is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
// Grawlix is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public
// License along with Grawlix.  If not, see
// <http://www.gnu.org/licenses/>.

#endregion

using System;
using Grawlix.Geometry;

namespace Grawlix.Application.Gui
{
	/// <summary>
	/// The result of testing mouse position within a control.
	/// </summary>
	public struct TestMouseResult : IEquatable<TestMouseResult>
	{
		/// <summary>
		/// The boundaries of the control.
		/// </summary>
		private Rect _bounds;

		/// <summary>
		/// The result of the mouse test.
		/// </summary>
		private Control _focus;

		/// <summary>
		/// The position of the mouse within the control.
		/// </summary>
		private Vector2 _position;

		/// <summary>
		/// The boundaries of the control.
		/// </summary>
		public Rect Bounds
		{
			get { return _bounds; }
			set { _bounds = value; }
		}

		/// <summary>
		/// The result of the mouse test.
		/// </summary>
		public Control Focus
		{
			get { return _focus; }
			set { _focus = value; }
		}

		/// <summary>
		/// The position of the mouse within the control.
		/// </summary>
		public Vector2 Position
		{
			get { return _position; }
			set { _position = value; }
		}

		/// <summary>
		/// Indicates whether the current object is equal to another
		/// object of the same type.
		/// </summary>
		/// <param name="other">An object to compare with this object.
		/// </param>
		/// <returns>
		/// true if the current object is equal to the 
		/// <paramref name="other"/> parameter; otherwise, false.
		/// </returns>
		public bool Equals(TestMouseResult other)
		{
			return other._position.Equals(_position) &&
			       other._bounds.Equals(_bounds) &&
			       Equals(other._focus, _focus);
		}

		/// <summary>
		/// Indicates whether this instance and a specified object are
		/// equal.
		/// </summary>
		/// <param name="obj">Another object to compare to.</param>
		/// <returns>
		/// true if <paramref name="obj"/> and this instance are the
		/// same type and represent the same value; otherwise, false.
		/// </returns>
		public override bool Equals(object obj)
		{
			if (obj.GetType() != typeof(TestMouseResult))
				return false;
			return Equals((TestMouseResult)obj);
		}

		/// <summary>
		/// Returns the hash code for this instance.
		/// </summary>
		/// <returns>
		/// A 32-bit signed integer that is the hash code for this
		/// instance.
		/// </returns>
		public override int GetHashCode()
		{
			unchecked
			{
				int result = _position.GetHashCode();
				result = (result * 397) ^ _bounds.GetHashCode();
				result = (result * 397) ^
				         (_focus != null ? _focus.GetHashCode() : 0);
				return result;
			}
		}

		/// <summary>
		/// Compares two <see cref="TestMouseResult"/> structures for
		/// equality.
		/// </summary>
		/// <param name="left">The left-hand side of the comparison.
		/// </param>
		/// <param name="right">The right-hand side of the comparison.
		/// </param>
		/// <returns><c>true</c> if equal; else <c>false</c>.</returns>
		public static bool operator ==(
			TestMouseResult left, TestMouseResult right)
		{
			return left.Equals(right);
		}

		/// <summary>
		/// Compares two <see cref="TestMouseResult"/> structures for
		/// inequality.
		/// </summary>
		/// <param name="left">The left-hand side of the comparison.
		/// </param>
		/// <param name="right">The right-hand side of the comparison.
		/// </param>
		/// <returns><c>false</c> if equal; else <c>tr</c>.</returns>
		public static bool operator !=(
			TestMouseResult left, TestMouseResult right)
		{
			return !left.Equals(right);
		}
	}
}